Project 1: Dragging in Google Maps
What: Interacting with Maps by dragging in Google Maps. * Where: http://maps.google.com * Who: Brian Eggleston & Michael Fischer = Overview of the Interaction = Google Maps was considered a revolutionary website when it was release. However, the website offered no actual new functionality. The basic functionality offered by Google Maps had been offered for several years by sites like MapQuest. What was revolutionary about Google Maps was that it allowed a level of interactivity that hadn't been seen before in a web-based map application. In previous map applications, when a user wanted to see a part of the map that was off-screen, the entire page would need to be reloaded with the new map view. This made the map very frustrating to use. Google Maps offered the user the ability to click on the map and drag it around to see different parts of the map. = Why is this interesting? = Being able to grab and drag elements on a webpage (including images) is not revolutionary. This was done all the time before Google Maps. However, the element that is supposed to be dragged in Google Maps is a map of the World. The file size for this image is huge. If this image were going to be downloaded so that it could be dragged, it would probably take an hour for the page to load. This is what prevented sites before Google Maps from employing the dragging technique on maps. = How does it work? = One possible solution to this problem would be to create maps that only cover a small area (e.g. a single city). Then, the user could drag around this map, and if they hit the end of the city, they wouldn't be able to drag or scroll any farther, and the page would need to be reloaded. However, Google wanted the user to be able to drag across the entire world, seamlessly. In order to do this, Google took the approach of only loading the parts of the map that are currently visible to the user. Although this is a fairly simple concept, its implementation is a little less obvious. In place of a single image tag, the Google Map page creates a div to represent the map. The world map is then divided up into small square tiles (each tile is 256x256 pixels). Each tile has a place where it belongs in this div in order to complete the image, and if all the images were loaded at once, it would look the same as if the world map was loaded as a single image. Google Maps uses javascript to determine what subsection of the map div is current visible on screen, based on the offset of the div relative to the div that contains it. Then, these coordinates are divided by the tile size to determine which tiles should be displayed for this part of the map. "img" elements are dynamically created and added to the map div, setting their absolute positions so they appear in the correct part of the div, and setting their 'src' attribute so that they show the correct part of the map. Once the 'src' attribute is set, the browser automatically sends a 'GET' request to the server for the image to display. Simultaneously, any tiles that have disappeared off the visible area of the screen are removed from the div. The tiles line up and appear to create a seamless image, and because they are positioned absolutely with respect to the map div, as the div is moved around (using basic dragging techniques as seen in class), the image tiles all move in sync with each other as the outer div moves. As the user drags, the page continues to keep track of what part of the div is on screen. It then adds 'img' elements as necessary to keep the screen filled with the map image, thereby creating the illusion that the entire world map was preloaded, when in fact, the map is being loaded lazily as its needed. This is why, when you drag very quickly, part of the map will appear to be blank for a second, until it gets filled in by image tiles. This is due to the latency in fetching the images from the server. This latency is reduced somewhat by also adding tiles that aren't currently on the screen, but that are near the edge of the screen, so that as the the user starts dragging, the nearby tiles are already preloaded. Google Maps also simulates an almost infinite zoom on the map by taking advantage of dynamic loading. When the user zooms in on a map, either by double clicking on an area or by using the scroll wheel, a javascript event is created that signals the current position of the mouse and which buttons were pressed. Temporarily, the current tile sizes are increased or decreased to create a smooth zooming effect. While the current image is being "zoomed" into, a request is made back to the server for a images that truly represent that level of zoom. These new tiles replace the old tiles, thereby improving the resolution of the image. The result is a smooth transition between different sets of mapping data. So, almost all of this interaction happens client-side, with very little server-side interaction needed. Javascript creates and adds the 'img' elements, and browsers automatically initiate 'GET' requests in response to the 'src' attribute changing on an 'img' elements. Because of this fact, this interaction could actually be performed by a simple server that only serves static content. It doesn't require any dynamic information from the server. See Stanford Map App for an example of this, using a static data server. = What can the class learn from it? = This interaction is an example of a more broad class of interactions. Essentially, the user is meant to interact with an element as if it were preloaded into the browser, when in fact, the file size of the element is much too large to actually preload. In this case, just enough information can be preloaded to display on the screen, and as the user being to interact with the element, the rest of the element can be loaded piece-by-piece as needed. An example of this might be a tree-view where the nesting is so deep that it doesn't make sense to preload the entire tree. In this case, it might make sense to just to load the top level of the tree, and perhaps its children. Then later levels of the tree could be fetched as the user starts opening nodes in the tree. In most cases, this would require an AJAX call. However, Google Maps actually avoids this by leveraging the fact that when the 'src' attribute of an 'img' tag is set, the browser automatically initiates a 'GET' call to the server, thereby making an AJAX call unnecessary. = How could improvements to the web make this functionality easier to implement = Many desktop frameworks have built-in support for figuring out what elements of a particular view are going to be visible on screen, and only loading those parts into main memory. This could theoretically be generalized to loading only the part of a picture that's visible on a screen. Therefore, this could, in principle, be taken care of completely by the framework without any explicit implementation by the programmer. This would require a framework to implement similar functionality to most desktop frameworks, as well as a change to http protocol in order for a browser to be able to request partial images.